package com.itheima.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 继承HttpServlet，在service方法里面模拟按照请求方式进行方法分发
 * 这里说一下，doget和dopost方法的不同就是获取请求参数的不同，后面getParameter这个方法帮我们解决了这个问题，所以其实两个方法可以合二为一
 * 写成别的方法也没有问题
 * doGet和doPost就是service按照请求方式分成的两个方法
 * 我们在service类里面使用请求路径来进行方法分发
 *
 * 执行流程：我们访问方法的路径，然后会去执行我们继承的BaseServlet里面的service方法，在service方法里面，我们获取访问路径，
 * 然后拿到其中的方法名，然后通过反射去执行子类中对应的方法
 *
 */
public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取访问brandServlet或者其他类型servlet
        //我们虽然访问的是方法的路径，但是方法的执行是在baseServlet里面调用
        String requestURI = req.getRequestURI();// /brand-base/brand/selectAll

        //2.获取方法名
        String[] split = requestURI.split("/");
        String methodName = split[split.length - 1];

        //3.获取对象servlet的字节码文件对象
        //此时的this就是代表brandServlet或者UserServlet
        //谁调用service方法，this就代表谁
        //我们定义brandServlet和UserServlet继承了BaseServlet，就变成了Servlet，servlet一定会去调用service方法
        //所以我们定义的servlet一定会去调用baseServlet里面的service方法
        //所以这里的this就代表的Base的子类
        Class<? extends BaseServlet> cls = this.getClass();

        //4.获取方法对象
        //获取方法对象之前，要将所有的方法都统一格式，传入request参数和response参数,统一参数类型
        /**
         *  public void selectAll(HttpServletRequest request, HttpServletResponse response)
         *  throws ServletException, IOException {
         *
         *     }
         */
        try {
            Method method = cls.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);

            //5.执行方法
            method.invoke(this,req,resp);//this代表的是调用方法的对象
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}
